package com.rh.number.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rh.number.entity.UserinfoEntity;
import com.rh.number.util.JwtUtil;
import io.jsonwebtoken.*;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtils;
    private final UserDetailsService userDetailsService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public JwtAuthenticationFilter(JwtUtil jwtUtils,
                                   UserDetailsService userDetailsService) {
        this.jwtUtils = jwtUtils;
        this.userDetailsService = userDetailsService;
    }

    private boolean shouldSkipAuthentication(HttpServletRequest request) {
        String uri = request.getRequestURI();
        return uri.startsWith("/api/auth/login") ||
                uri.startsWith("/api/auth/register");
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        try {
            // 1. 检查请求路径是否需要跳过验证
            if (shouldSkipAuthentication(request)) {
                filterChain.doFilter(request, response);
                return;
            }

            // 2. 验证令牌
            String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                handleJwtError(response, "缺失或错误的Authorization头", HttpStatus.BAD_REQUEST);
                return;
            }

            String token = authHeader.substring(7);
            Claims claims = jwtUtils.validateToken(token);

            // 3. 加载用户信息
            UserDetails userDetails = userDetailsService.loadUserByUsername(claims.getSubject());
            buildAuthenticationContext(userDetails);

            // 4. 继续过滤器链
            filterChain.doFilter(request, response);

        } catch (ExpiredJwtException ex) {
            handleJwtError(response, "令牌已过期", HttpStatus.UNAUTHORIZED);
        } catch (MalformedJwtException | SignatureException ex) {
            handleJwtError(response, "无效令牌格式", HttpStatus.BAD_REQUEST);
        } catch (JwtException ex) {
            handleJwtError(response, "令牌验证失败", HttpStatus.UNAUTHORIZED);
        } catch (UsernameNotFoundException ex) {
            handleJwtError(response, "用户不存在", HttpStatus.NOT_FOUND);
        } catch (Exception ex) {
            handleJwtError(response, "服务器内部错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }


    private UserDetails loadUserDetails(String username) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (userDetails == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return userDetails;
    }

    private void buildAuthenticationContext(UserDetails userDetails) {
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );

        if (userDetails instanceof UserinfoEntity) {
            Map<String, Object> details = new HashMap<>();
            details.put("role", ((UserinfoEntity) userDetails).getRole());
            authentication.setDetails(details);
        }

        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private void handleJwtError(HttpServletResponse response,
                                String message,
                                HttpStatus status) throws IOException {
        response.setStatus(status.value());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(
                Map.of(
                        "timestamp", new Date(),
                        "status", status.value(),
                        "error", status.getReasonPhrase(),
                        "message", message,
                        "code", status.value() == 401 ? "AUTH_FAILED" : "INVALID_REQUEST"
                )
        ));
    }

    private void sendErrorResponse(HttpServletResponse response,
                                   String message,
                                   HttpStatus status) throws IOException {
        handleJwtError(response, message, status);
    }


}